package com.jxl.dnd.charactercreator.vo
{
	import com.jxl.dnd.charactercreator.vo.abilityscores.AbilityScores;
	import com.jxl.dnd.charactercreator.vo.characterclasses.CharacterClass;
	import com.jxl.dnd.charactercreator.vo.feats.Feat;
	import com.jxl.dnd.charactercreator.vo.races.Race;
	import com.jxl.dnd.charactercreator.vo.skills.Skill;
	
	import flash.events.EventDispatcher;
	
	import mx.collections.ArrayCollection;

	[Bindable]
	public class Character extends EventDispatcher
	{
		
		public var name:String;
		public var abilityScores:AbilityScores;
		public var race:Race;
		public var characterClass:CharacterClass;
		public var level:uint;
		[ArrayElementType("com.jxl.dnd.charactercreator.vo.skills.Skill")]
		public var skills:ArrayCollection;
		[ArrayElementType("com.jxl.dnd.charactercreator.vo.feats.Feat")]
		public var feats:ArrayCollection;
		
		public var size:String;
		public var age:String;
		public var gender:String;
		public var height:String;
		public var weight:String;
		public var alignment:String;
		public var deity:String;
		public var affiliation:String;
		
		protected var _experience:uint;
		protected var _initiative:int;
		
		public function get experience():uint { return _experience; }
		public function set experience(value:uint):void
		{
			_experience = value;
			var targettedLevel:uint = getExperienceLevel(_experience);
			//DebugWindow.header();
			//DebugWindow.debug("Character::experience, value: " + value + ", targettedLevel: " + targettedLevel);
			if(level != targettedLevel)
			{
				level = targettedLevel;
			}
		}
		
		[Event(event="initiativeChanged")]
		public function get initiative():int
		{
			if(abilityScores != null)
			{
				if(abilityScores.dexterity != null)
				{
					return abilityScores.dexterity.abilityModifier + (Math.round(level / 2));
				}
				else
				{
					return 0;
				}
			}
			else
			{
				return 0;
			}
			return 0;
		}
		public function set initiative(value:int):void
		{
			_initiative = 0;
		}
		
		public function Character():void
		{
			super();
			
			name			= "Default Adventurer";
			abilityScores	= new AbilityScores();
			race			= new Race();
			characterClass	= new CharacterClass();
			level			= 4;
			skills			= new ArrayCollection();
			feats			= new ArrayCollection();
			
			size			= "Medium";
			age				= "18";
			gender			= "Male";
			height			= "5' 11''";
			weight			= "150 lbs";
			alignment		= "Neutral";
			deity			= "";
			affiliation		= "";
			
			abilityScores.addEventListener("dexterityChanged", onAbilityScoresChanged);
		}
		
		public function getExperienceLevel(xp:uint):uint
		{
			if(isNaN(xp) == true) return 1;
			
			//DebugWindow.debug("case (xp > 82999 && xp < 99000): " + (xp > 82999 && xp < 99000));
			
			
			if(xp < 1000)							return 1;
			if(xp > 999 && xp < 2250)				return 2;
			if(xp > 2249 && xp < 3750)				return 3;
			if(xp > 3749 && xp < 5500)				return 4;
			if(xp > 5499 && xp < 7500)				return 5;
			if(xp > 7499 && xp < 10000)				return 6;
			if(xp > 9999 && xp < 13000)				return 7;
			if(xp > 12999 && xp < 16500)			return 8;
			if(xp > 16499 && xp < 20500)			return 9;
			if(xp > 20499 && xp < 26000)			return 10;
			if(xp > 25999 && xp < 32000)			return 11;
			if(xp > 31999 && xp < 39000) 			return 12;
			if(xp > 38999 && xp < 47000)			return 13;
			if(xp > 46999 && xp < 57000) 			return 14;
			if(xp > 56999 && xp < 69000)			return 15;
			if(xp > 68999 && xp < 83000) 			return 16;
			if(xp > 82999 && xp < 99000)			return 17;
			if(xp > 98999 && xp < 119000) 			return 18;
			if(xp > 118999 && xp < 143000)			return 19;
			if(xp > 142999 && xp < 175000)			return 20;
			if(xp > 174999 && xp < 210000) 			return 21;
			if(xp > 209999 && xp < 255000)			return 22;
			if(xp > 254999 && xp < 310000) 			return 23;
			if(xp > 309999 && xp < 375000) 			return 24;
			if(xp > 374999 && xp < 450000)			return 25;
			if(xp > 449999 && xp < 550000) 			return 26;
			if(xp > 549999 && xp < 675000)			return 27;
			if(xp > 674999 && xp < 825000)			return 28;
			if(xp > 824999 && xp < 1000000)			return 29;
			if(xp > 999999)							return 30;
			return 1;
		}
		
		protected function onAbilityScoresChanged(event:Event):void
		{
			//DebugWindow.header();
			//DebugWindow.debug("Character::onAbilityScoresChanged");
			//dispatchEvent(new Event("initiativeChanged", true));
			initiative = 1;
		}
		
		public function buildFromObject(obj:Object):void
		{
			this.name				= obj.name;
			
			this.abilityScores		= new AbilityScores();
			this.abilityScores.buildFromObject(obj.abilityScores);
			
			this.race				= new Race();
			this.race.buildFromObject(obj.race);
			
			this.characterClass		= new CharacterClass();
			this.characterClass.buildFromObject(obj.characterClass);
			
			this.level				= obj.level;
			this.skills			 	= new ArrayCollection();
			if(obj.skills != null)
			{
				var skillLen:int 		= obj.skills.length;
				var skillObject:Object;
				var newSkill:Skill;
				for(var index:uint = 0; index < skillLen; index++)
				{
					skillObject = obj.skills[index];
					newSkill = new Skill();
					newSkill.buildFromObject(skillObject);
					skills.addItem(newSkill);
				}
			}
			
			this.feats				= new ArrayCollection();
			if(obj.feats != null)
			{
				var featLen:int 		= obj.feats.length;
				var featObject:Object;
				var newFeat:Feat;
				for(index = 0; index < featLen; index++)
				{
					featObject = obj.feats[index];
					newFeat = new Feat();
					newFeat.buildFromObject(featObject);
					feats.addItem(featObject);
				}
			}
			
			this.size				= obj.size;
			this.age				= obj.age;
			this.gender				= obj.gender;
			this.height				= obj.height;
			this.weight				= obj.weight;
			this.alignment			= obj.alignment;
			this.deity				= obj.deity;
			this.affiliation		= obj.affiliation;
			this.experience			= obj.experience;
		}
		
		public function toObject():Object
		{
			var obj:Object				= new Object();
			obj.name					= name;
			obj.abilityScores			= abilityScores.toObject();
			obj.race					= race.toObject();
			obj.characterClass			= characterClass.toObject();
			obj.level					= level;
			obj.skills					= [];
			var len:int 				= skills.length;
			var skill:Skill;
			for(var index:uint = 0; index < len; index++)
			{
				skill = skills.getItemAt(index) as Skill;
				obj.skills[index] = skill.toObject();
			}
			obj.feats					= [];
			len							= feats.length;
			var feat:Feat;
			for(index = 0; index < len; index++)
			{
				feat = feats.getItemAt(index) as Feat;
				obj.feats[index] = feat.toObject();
			}
			obj.size					= size;
			obj.age						= age;
			obj.gender					= gender;
			obj.height					= height;
			obj.weight					= weight;
			obj.alignment				= alignment;
			obj.deity					= deity;
			obj.affiliation				= affiliation;
			obj.experience 				= _experience;
			
			return obj;
		}
		
		public function toXML():XML
		{
			var myXML:XML = 
				<character>
					<name>{name}</name>
					<level>{level}</level>
					<size>{size}</size>
					<age>{age}</age>
					<gender>{gender}</gender>
					<height>{height}</height>
					<weight>{weight}</weight>
					<alignment>{alignment}</alignment>
					<deity>{deity}</deity>
					<affiliation>{affiliation}</affiliation>
					<experience>{experience}</experience>
					<initiative>{initiative}</initiative>
				</character>;
			
			if(abilityScores != null) myXML.appendChild(abilityScores.toXML());
			if(race != null) myXML.appendChild(race.toXML());
			if(characterClass != null) myXML.appendChild(characterClass.toXML());
			
			var len:int;
			var index:uint;
			var skillsXML:XML = <skills />;
			myXML.appendChild(skillsXML);
			var featsXML:XML = <feats />;
			myXML.appendChild(featsXML);
			if(skills != null)
			{
				len = skills.length;
				var skill:Skill;
				for(index = 0; index < len; index++)
				{
					skill = skills.getItemAt(index) as Skill;
					skillsXML.appendChild(skill.toXML());
				}
			}
			
			if(feats != null)
			{
				len = feats.length;
				var feat:Feat;
				for(index = 0; index < len; index++)
				{
					feat = feats.getItemAt(index) as Feat;
					featsXML.appendChild(feat.toXML());
				}
			}
			
			return myXML;
		}
		
		public function buildFromXML(xml:XML):void
		{
			for each(var characterNode:XML in xml..character)
			{
				name						= characterNode.name;
				abilityScores.buildFromXML(xml);
				race.buildFromXML(xml);
				characterClass.buildFromXML(xml);
				level 						= characterNode.level;
				skills 						= new ArrayCollection();
				var skill:Skill;
				for each(var skillNode:XML in characterNode.skills)
				{
					skill = new Skill();
					skill.buildFromXML(skillNode);
					skills.addItem(skill);
				}
				
				feats 						= new ArrayCollection();
				var feat:Feat;
				for each(var featNode:XML in characterNode.feats)
				{
					feat = new Feat();
					feat.buildFromXML(xml);
					feats.addItem(feat);
				}
				
				size						= characterNode.size;
				age							= characterNode.age;
				gender						= characterNode.gender;
				height						= characterNode.height;
				weight						= characterNode.weight;
				alignment					= characterNode.alignment;
				deity						= characterNode.deity;
				affiliation					= characterNode.affiliation;
				_experience					= characterNode.experience;
			}
		}
		
		
		
	}
}